package br.com.lazyprogrammer.spaceshooter.model;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import br.com.lazyprogrammer.spaceshooter.model.listener.WorldListener;
import br.com.lazyprogrammer.spaceshooter.model.renderer.WorldRenderer;
import br.com.limaogames.framework.math.OverlapTester;

/**
 * Created by LimaoGames on 19/8/2014.
 */
public class World implements WorldListener {

    public static final int WORLD_STATE_RUNNING = 0;
    public static final int WORLD_STATE_PAUSED = 1;
    public static final int WORLD_STATE_GAME_OVER = 2;
    public static final int WORLD_STATE_START = 3;

    public static final int MAX_ENEMY = 15;
    public static final int MAX_METEOR = 20;
    public static final int MAX_SHOT = 30;

    public static Player player;
    public static List<Enemy> enemies = new ArrayList<Enemy>();
    public static List<Meteor> meteors = new ArrayList<Meteor>();
    public static List<Shot> shots = new ArrayList<Shot>();

    public int gameLevel = 1, state, score = 0;

    Random random = new Random();

    public World() {
        player = new Player(WorldRenderer.FRUSTUM_WIDTH / 2, WorldRenderer.FRUSTUM_HEIGHT / 2);

        state = WORLD_STATE_RUNNING;
        createMeteor();
    }

    @Override
    public void createMeteor() {
        if (meteors.size() >= 2 * gameLevel || meteors.size() > MAX_METEOR)
            return;
        int meteorSize = random.nextInt(2);
        float speed = Meteor.getSpeed(meteorSize);
        float width = Meteor.getWidth(meteorSize);
        float height = Meteor.getHeight(meteorSize);
        float vx = speed * (random.nextFloat() - 0.5f);
        float vy = speed * (random.nextFloat() - 0.5f);
        float x = vx <= 0 ? WorldRenderer.FRUSTUM_WIDTH + width : -width;
        float y = vy <= 0 ? WorldRenderer.FRUSTUM_HEIGHT + height : -height;
        if (vx <= 0)
            vx -= speed;
        else
            vx += speed;
        if (vy <= 0)
            vy -= speed;
        else
            vy += speed;
        meteors.add(Meteor.create(random, meteorSize, x, y, vx, vy));
    }

    public void update(float deltaTime, float accelX) {
        updatePlayerShip(deltaTime, accelX);
        updateMeteors(deltaTime);
        updateShots(deltaTime);
        checkCollisions();
    }

    public void updateMeteors(float deltaTime) {
        int len = meteors.size();
        for (int i = 0; i < len; i++)
            meteors.get(i).update(deltaTime);
    }

    public void updatePlayerShip(float deltaTime, float accelX) {
        player.angle += accelX / 10 * Player.PLAYER_MOVE_VELOCITY;
        player.update(deltaTime);
    }

    public void updateShots(float deltaTime) {
        int len = shots.size();
        for (int i = 0; i < len; i++)
            shots.get(i).update(deltaTime);
    }

    public void checkCollisions() {
        checkCollisionsBetweenMeteorsAndMeteors();
        checkCollisionBetweenPlayerAndMeteors();
        checkCollisionsBetweenShotsAndMeteors();
    }

    @Override
    public void spaceShoot() {
        if (shots.size() > MAX_SHOT)
            shots.remove(0);
        shots.add(new Shot(player.position.x, player.position.y, 1, 1, player.angle));
    }

    private void checkCollisionsBetweenMeteorsAndMeteors() {
        for (int i = 0; i < meteors.size() - 1; i++) {
            for (int j = (i + 1); j < meteors.size(); j++) {
                if (OverlapTester.overlapRectangles(meteors.get(i).bounds, meteors.get(j).bounds)) {
                    meteors.get(i).velocity.x = -meteors.get(i).velocity.x;
                    meteors.get(i).velocity.y = -meteors.get(i).velocity.y;
                    meteors.get(j).velocity.x = -meteors.get(j).velocity.x;
                    meteors.get(j).velocity.y = -meteors.get(j).velocity.y;
                }
            }
        }
    }

    private void checkCollisionBetweenPlayerAndMeteors() {
        for (int i = 0; i < meteors.size(); i++) {
            if (OverlapTester.overlapRectangles(player.bounds, meteors.get(i).bounds)) {
                player.hit(1);
                if (player.healthBar <= 0) {
                    state = WORLD_STATE_GAME_OVER;
                    return;
                }
                meteors.get(i).hit(1);
                if (meteors.get(i).healthBar <= 0) {
                    meteors.remove(i);
                    createMeteor();
                    return;
                }
                meteors.get(i).velocity.x = -meteors.get(i).velocity.x;
                meteors.get(i).velocity.y = -meteors.get(i).velocity.y;
                //player.velocity.set(-meteors.get(i).velocity.x / 10, -meteors.get(i).velocity.y / 10);
            }
        }
    }

    private void checkCollisionsBetweenShotsAndMeteors() {
        for (int i = 0; i < meteors.size(); i++) {
            for (int j = 0; j < shots.size(); j++) {
                if (OverlapTester.overlapRectangles(meteors.get(i).bounds, shots.get(j).bounds)) {
                    Shot shot = shots.remove(j);
                    meteors.get(i).hit(shot.DAMAGE);
                    if (meteors.get(i).healthBar <= 0) {
                        meteors.remove(i);
                        createMeteor();
                        return;
                    }
                    meteors.get(i).velocity.x -= shot.DAMAGE / 50;
                    meteors.get(i).velocity.y -= shot.DAMAGE / 50;
                    j--;
                }
            }
        }
    }

}
